<?php
/**
 * description
 *
 * @category   Module name
 * @package    PSR
 * @subpackage Documentation\API
 * @author     yangth
 * @date       2023/2/27
 * @time       4:01 下午
 */

namespace Buu\Modules\EsStandard\Controllers;


use App\Library\Common;
use App\Models\DbTables;
use App\Models\EsIndex;
use App\Models\EsIndexTask;
use App\Models\EsSourceMapping;
use Doraemon\tools\Curl;
use Doraemon\tools\HhzEnv;
use Encore\Admin\Facades\Admin;
use Encore\Admin\Grid;
use Encore\Admin\Layout\Content;
use Encore\Admin\Form;
use Illuminate\Http\Request;
use Illuminate\Support\MessageBag;
use Encore\Admin\Controllers\AdminController;

class EsIndexTaskController extends AdminController
{
	protected $title = "Es索引任务管理";
    private const DEPLOY_CONFIG_File = "DroneConfigMap.json";
    public static array $aDroneConfig = [];


    public function __construct()
    {
        $dir = dirname( __DIR__) . "/Lib/" . self::DEPLOY_CONFIG_File;
        $sConfig = file_get_contents($dir);
        $configMap = json_decode($sConfig, true, 512, JSON_THROW_ON_ERROR);

        self::$aDroneConfig = $configMap['bifrost'];
    }

	public function index(Content $content)
	{
        $content->breadcrumb([
            'text' => $this->title
        ]);
        return parent::index($content);
	}

	protected function grid()
	{
        $grid = new Grid(new EsIndexTask());
        $grid->paginate(50);
        $grid->disableFilter();
        $grid->disableExport();

        $grid->column('id', 'ID');
        $grid->column('es_index_id', 'Es索引')->display(function () {
            return 'bf_' . EsIndex::find($this->es_index_id)->name;
        })->label();
        $grid->column('db_tables_id', '映射数据表')->display(function () {
            return DbTables::find($this->db_tables_id)->table_name;
        });
        $grid->column('exec_type', '执行类型')->using(EsIndexTask::EXEC_TYPE, '未知');
        $grid->column('start_time', '开始时间')->display(function () {
            return $this->start_time ? date('Y-m-d H:i:s', $this->start_time) : '';
        })->label();
        $grid->column('exec_status', '执行状态')->using(EsIndexTask::EXEC_STATUS, '未知');
        $grid->column('condition_raw_sql', '条件');
        $grid->column('data_status', '状态')->using(EsIndex::DATA_STATUS, '未知')->label([
            EsIndex::STATUS_NORMAL => 'success',
            EsIndex::STATUS_DELETE => 'warning'
        ]);
        $grid->column('add_username', '服务负责人');
        $grid->actions(function (Grid\Displayers\Actions $actions) {
            $actions->disableDelete();
            if ($actions->row->data_status == EsIndexTask::STATUS_NORMAL) {
                if ($actions->row->exec_status == EsIndexTask::EXEC_STATUS_WAIT) {
                    $actions->append("<a href=\"/admin/EsStandard/es-index-task/{$actions->row->id}/start\" style='color: green; margin-left: 10px;'><i class='fa fa-cogs'></i>立即执行</a>");
                } else if($actions->row->exec_status == EsIndexTask::EXEC_STATUS_FINISH) {
                    $actions->append("<a href=\"/admin/EsStandard/es-index-task/{$actions->row->id}/start\" style='color: green; margin-left: 10px;'><i class='fa fa-cogs'></i>重新执行</a>");
                }
            }
        });
        return $grid;
	}

    /**
     * 表单.
     *
     * @return \Encore\Admin\Form
     */
    public function form()
    {
        $form = new Form(new EsIndexTask());
        $list = EsSourceMapping::all()->toArray();
        $esIndexDbTables = [];
        foreach ($list as $item) {
            $esIndexDbTables[$item['es_index_id']] = $esIndexDbTables[$item['es_index_id']] ?? [];
            $esIndexDbTables[$item['es_index_id']] = array_unique(array_merge($esIndexDbTables[$item['es_index_id']], [$item['db_tables_id']]));
        }
        $form->select('es_index_id', 'Es索引')->options(
            EsIndex::whereIn('id', array_keys($esIndexDbTables))->get()->pluck('name', 'id')
        )->load('db_tables_id', '/admin/EsStandard/es-db-mapping/getDbTablesIds')->required();
        $form->select('db_tables_id', '映射数据表')->options(function () use ($esIndexDbTables) {
            if ($this->es_index_id) {
                return DbTables::whereIn('id', array_values($esIndexDbTables[$this->es_index_id]))->get()->pluck('table_name', 'id');
            } else {
                return [];
            }
        })->required();
        $form->select('exec_type', '执行类型')->options(EsIndexTask::EXEC_TYPE)->default(EsIndexTask::EXEC_TYPE_MANUAL);
        $form->datetime('start_at', '开始时间')->format('YYYY-MM-DD HH:mm:ss')->default('');
        $form->text('condition_raw_sql', '条件（原生Sql形式）');
        $form->radio('data_status', '状态')->options(EsIndexTask::DATA_STATUS)->default(EsIndexTask::STATUS_NORMAL)->required();
        $form->hidden('add_time');
        $form->hidden('update_time');
        $form->hidden('add_username');
        $form->hidden('update_username');
        $form->hidden('id');
        $form->setAction('save');

        $form->tools(function (Form\Tools $tools) {
            $tools->disableView();
            $tools->disableDelete();
        });

        return $form;
    }

    /**
     * 添加保存
     */
    public function save(Request $request)
    {
        try {
            $aParams = $request->all();
            $rules = [
                "es_index_id"  => "required|integer",
                "exec_type"    => "required|integer",
            ];
            $msg = Common::validatorRule($rules, $aParams);
            if ($msg !== true) {
                throw new \Exception($msg);
            }
            if (is_numeric($aParams['db_tables_id'])) {
                $dbTablesId = $aParams['db_tables_id'];
            } else {
                $esSourceMapping = EsSourceMapping::query()->where('es_index_id', '=', $aParams['es_index_id'])->get()->toArray();
                $dbTables = DbTables::query()->whereIn('id', array_column($esSourceMapping, 'db_tables_id'))
                    ->where('table_name', $aParams['db_tables_id'])
                    ->first('id')->toArray();
                $dbTablesId = $dbTables['id'] ?? 0;
            }
            if (empty($dbTablesId)) {
                $error = new MessageBag([
                    'title' => '映射数据表不存在，请重试'
                ]);
                return back()->with(compact('error'))->withInput();
            }

            $data = [
                'es_index_id' => $aParams['es_index_id'],
                'db_tables_id' => $dbTablesId,
                'exec_type' => $aParams['exec_type'],
                'condition_raw_sql' => $aParams['condition_raw_sql'],
                'data_status' => $aParams['data_status'],
            ];
            if ($aParams['exec_type'] == EsIndexTask::EXEC_TYPE_MANUAL) {
                $data['start_time'] = 0;
            } else if ($aParams['exec_type'] == EsIndexTask::EXEC_TYPE_TIMMER) {
                if (empty($aParams['start_at'])) {
                    $error = new MessageBag([
                        'title' => '请填写定时开始时间'
                    ]);
                    return back()->with(compact('error'))->withInput();
                }
                $data['start_time'] = strtotime($aParams['start_at']);
            }
            $id = $aParams['id'] ?? 0;
            $data['update_time'] = time();
            $data['update_username'] = Admin::user()->username;
            if (empty($id)) {
                $data['add_time'] = time();
                $data['add_username'] = Admin::user()->username;
                $id = EsIndexTask::saveData($data);
            } else {
                $count = EsIndexTask::query()->where([
                    'es_index_id' => $aParams['es_index_id'],
                    'exec_status' => EsIndexTask::EXEC_STATUS_WAIT,
                    'data_status' => EsIndexTask::STATUS_NORMAL,
                ])->whereNotIn('id', [$id])->count('id');
                if ($count >=1) {
                    $error = new MessageBag([
                        'title' => '该索引下有任务未完成，请稍后再添加！'
                    ]);
                    return back()->with(compact('error'))->withInput();
                }
                $data['id'] = $id;
                EsIndexTask::saveInfo($id, $data);
            }
            $success = new MessageBag([
                'title' => '成功',
            ]);
        } catch (\Exception $e) {
            $error = new MessageBag([
                'title' => $e->getMessage(),
            ]);
            return back()->with(compact('error'))->withInput();
        }
        return redirect('/admin/EsStandard/es-index-task')->with(compact('success'));
    }

    /**
     * 启动任务
     */
    public function start(Request $request, $id)
    {
        try {
            $info = EsIndexTask::query()->where([
                'id' => $id,
                'data_status' => EsIndexTask::STATUS_NORMAL,
            ])->first()->toArray();
            if (empty($info)) {
                throw new \Exception('ID错误，数据不存在');
            }
            //重新打开且设置执行类型为手动
            EsIndexTask::saveInfo($id, [
                'exec_status' => EsIndexTask::EXEC_STATUS_WAIT,
                'exec_type' => EsIndexTask::EXEC_TYPE_MANUAL,
                'start_time' => 0,
            ]);
            //调用Bifrost平台接口启动任务
            $globalConfig = self::$aDroneConfig['global_config'];
            if (HhzEnv::isProduction()) {
                $globalConfig = $globalConfig['production'];
            } else if (HhzEnv::isTest()) {
                $globalConfig = $globalConfig['qa'];
            } else {
                $globalConfig = $globalConfig['hhz-dev'];
            }
            $domain = $globalConfig['domain'];
            $url = rtrim($domain, "/") . "/" . ltrim(self::$aDroneConfig['apis']['history_start']['url'], "/");
            $params = ['token' => $globalConfig['token'], 'task_id' => $info['id']];
            $params = json_encode($params, JSON_THROW_ON_ERROR);
            $result = Curl::postRawRequest($url, $params);
            if(!isset($result["code"]) || $result["code"] != 1){
                throw new \Exception('接口请求失败：' . ($result['msg'] ?? '服务异常'));
            }
            $success = new MessageBag([
                'title' => '成功',
            ]);
        } catch (\Exception $e) {
            $error = new MessageBag([
                'title' => $e->getMessage(),
            ]);
            return back()->with(compact('error'))->withInput();
        }
        return redirect('/admin/EsStandard/es-index-task')->with(compact('success'));
    }
}